﻿Imports System.Web
Imports System.Web.Services
Imports System.Net

Public Class download
    Implements System.Web.IHttpHandler

    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        Dim id As Integer
        Integer.TryParse(context.Request.QueryString("id"), id)

        Dim s = FMW.FMWBO.GetSongByID(id)
        If s Is Nothing Then
            context.Response.End()
        End If

        Dim url = s.DownloadURL


        url = url.Replace("download.apunkabollywood.com", "208.93.192.88")

        Dim resp = context.Response

        'Create a stream for the file
        Dim stream As IO.Stream = Nothing

        'This controls how many bytes to read at a time and send to the client
        Dim bytesToRead As Integer = 10000

        ' Buffer to read bytes in chunk size specified above
        Dim buffer As Byte() = New [Byte](bytesToRead - 1) {}

        ' The number of bytes read
        Try
            'Create a WebRequest to get the file
            Dim fileReq As HttpWebRequest = DirectCast(HttpWebRequest.Create(url), HttpWebRequest)
            
            'Create a response for this request
            Dim fileResp As HttpWebResponse

            Dim etag As String
            Dim request = context.Request
            Dim startIndex, toIndex, responseLength As Integer
            'If context.Request.Headers("If-None-Match") = etag Then
            '    context.Response.StatusCode = CInt(HttpStatusCode.NotModified)
            '    context.Response.[End]()
            'End If


            'If request.Headers("Range") IsNot Nothing AndAlso (request.Headers("If-Range") Is Nothing OrElse request.Headers("IF-Range") = etag) Then
            If request.Headers("Range") IsNot Nothing Then
                Dim match = Regex.Match(request.Headers("Range"), "bytes=(\d*)-(\d*)")
                startIndex = Parse(Of Integer)(match.Groups(1).Value)
                toIndex = Parse(Of Integer)(match.Groups(2).Value)
                If startIndex > 0 AndAlso toIndex > 0 Then
                    fileReq.AddRange(startIndex, toIndex)
                ElseIf startIndex > 0 Then
                    fileReq.AddRange(startIndex)
                End If
                'responseLength = (If(Parse(Of System.Nullable(Of Integer))(match.Groups(2).Value) + 1, fileResp.ContentLength)) - startIndex
                'response.StatusCode = CInt(HttpStatusCode.PartialContent)

                'response.Headers("Content-Range") = ("bytes " & startIndex & "-" & (startIndex + responseLength - 1) & "/") + fileResp.ContentLength
            End If

            'fileReq.Headers.Add("If-None-Match", "73c81e8-9cc641-4be9534f94ac0")
            fileResp = DirectCast(fileReq.GetResponse(), HttpWebResponse)

            responseLength = fileResp.ContentLength

            For i = 0 To fileResp.Headers.Count - 1

                Dim key = fileResp.Headers.GetKey(i)
                If key = "Content-Disposition" Then Continue For
                resp.AppendHeader(key, fileResp.Headers(i))
            Next

            'Content-Range: bytes 8192-10274368/10274369
            If startIndex = 0 AndAlso toIndex = 0 Then
                'resp.AppendHeader("Content-Range", "bytes " & startIndex & "-" & fileResp.ContentLength - 1 & "/" & fileResp.ContentLength)
            End If

            resp.StatusCode = fileResp.StatusCode

            'resp.Headers("Content-Range") = ("bytes " & startIndex & "-" & (startIndex + responseLength - 1) & "/") + fileResp.ContentLength


            'resp.AppendHeader("Accept-Ranges", "bytes")
            'resp.Headers("Content-Length") = responseLength.ToString()
            resp.Cache.SetCacheability(HttpCacheability.[Public])
            'required for etag output
            'etag = fileResp.Headers("")
            If Not String.IsNullOrEmpty(fileResp.Headers("ETag")) Then
                resp.Cache.SetETag(fileResp.Headers("ETag"))
            End If

            Dim ext = s.DownloadURL.Split(".").Last
            resp.ContentType = fileResp.ContentType
            resp.AppendHeader("Content-Disposition", "attachment; filename=""" & s.DisplayTitle & "." & ext & """")




            'required for IE9 resumable downloads


            'If fileReq.ContentLength > 0 Then
            '    fileResp.ContentLength = fileReq.ContentLength
            'End If

            'Get the Stream returned from the response
            stream = fileResp.GetResponseStream()

            ' prepare the response to the client. resp is the client Response

            'Indicate the type of data being sent
            
            'Select Case ext
            '    Case ".wma"
            '        resp.ContentType = "audio/x-ms-wma"
            '    Case ".wav"
            '        resp.ContentType = "audio/wav"
            '    Case ".mp3"
            '        resp.ContentType = "audio/mpeg3"
            '    Case Else
            '        resp.ContentType = "audio/mpeg3"
            'End Select


            'Name the file 

            'resp.AddHeader("Content-Length", fileResp.ContentLength.ToString())

            Dim length As Integer
            Do
                ' Verify that the client is connected.
                If resp.IsClientConnected Then
                    ' Read data into the buffer.
                    length = stream.Read(buffer, 0, bytesToRead)

                    ' and write it out to the response's output stream
                    resp.OutputStream.Write(buffer, 0, length)

                    ' Flush the data
                    resp.Flush()

                    'Clear the buffer
                    buffer = New [Byte](bytesToRead - 1) {}
                Else
                    ' cancel the download if client has disconnected
                    length = -1
                End If
                'Repeat until no data is read
            Loop While length > 0
        Finally
            If stream IsNot Nothing Then
                'Close the input stream
                stream.Close()
            End If
        End Try

    End Sub

    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property


    Public Shared Function Parse(Of T)(ByVal value As Object) As T
        'convert value to string to allow conversion from types like float to int
        'converter.IsValid only works since .NET4 but still returns invalid values for a few cases like NULL for Unit
        Try
            Return DirectCast(System.ComponentModel.TypeDescriptor.GetConverter(GetType(T)).ConvertFrom(value.ToString()), T)
        Catch generatedExceptionName As Exception
            Return Nothing
        End Try
    End Function

End Class